package rpa

import (
	"context"
	"errors"
	"git.mycaigou.com/gfyx/micro-gfyx-api/infrastructure/dto/rpa"
	rpa2 "git.mycaigou.com/gfyx/micro-gfyx-api/infrastructure/repository/rpa"
	rpaPb "git.mycaigou.com/gfyx/micro-gfyx-api/proto/micro_gfyx_oppty_service_proto/micro-gfyx-oppty-service/rpa"
	"git.myscrm.cn/golang/stark/v4"
	"strconv"
)

const (
	RPA_CMD_POST = "post"
	RPA_CMD_GET  = "get"
)

var (
	Rpa_Version_20231010 = rpa.RpaVersion{
		Version:    1,
		RpaVersion: "1.0.0",
	}
)

type RpaCmdService struct {
	rpaCmdMap     map[int32]map[int64]rpa.RpaHandler
	rccService    RccServiceIface
	rpaRepository rpa2.RpaRepositoryIface
}

// 构造展示
func NewRpaCmdService(rccService RccServiceIface, rpaRepository rpa2.RpaRepositoryIface) RpaCmdServiceIface {
	rpaCmdMap := make(map[int32]map[int64]rpa.RpaHandler)

	cmdService := &RpaCmdService{
		rpaCmdMap:     rpaCmdMap,
		rccService:    rccService,
		rpaRepository: rpaRepository,
	}

	cmdService.initHandlerConfig()

	return cmdService
}

// 初始化
func (s *RpaCmdService) initHandlerConfig() {
	// 初始化rcc web
	s.rpaCmdMap[rpa.BUSS_TYPE_RCC_WEB] = s.rccService.GetCmdHandlers()
}

func (s *RpaCmdService) checkVersion(ctx context.Context, ver rpa.RpaVersion) (bool, error) {
	switch ver.Version {
	case Rpa_Version_20231010.Version:
		//switch ver.RpaVersion {
		//case Rpa_Version_20231010.RpaVersion:
		//	return true, nil
		//default:
		//	return false, errors.New("rpa客户端版本不兼容")
		//}

		return true, nil
	default:
		return false, errors.New("协议版本版本不兼容")
	}
}

func (s *RpaCmdService) RpaTenantInit(ctx context.Context, tenantCode, userMobile, version, rpaVersion string) (string, error) {
	//cacheRedis, _ := cache.Redis()
	//cacheKey := fmt.Sprintf("gfyx-rpa-tenantcode:%s", tenantCode)
	//secret := uuid.New().String()
	//_, err := cacheRedis.Set(ctx, cacheKey, secret, true, 365*24*3600)
	//if err != nil {
	//	return "", err
	//}

	rpaConfig := &rpaPb.RpaConfig{
		TenantCode: tenantCode,
		UserMobile: userMobile,
		Version:    version,
		RpaVersion: rpaVersion,
		//MachineCode: machineCode,
	}
	request := &rpaPb.SaveRpaConfigRequest{
		Data: rpaConfig,
	}
	resp, err := s.rpaRepository.SaveRpaConfigData(ctx, request)
	if err != nil {
		stark.Logger.Errorf(ctx, "RpaTenantInit-err: %+v", err)
		return "", err
	}
	secret := resp.SecrectKey

	//todo 保存初始化租户信息

	return secret, nil
}

// 启动登录验证
func (s *RpaCmdService) RpaStart(ctx context.Context, param *rpa.RpaStartParam) (string, error) {
	// 0. 检查参数是否OK
	ver := rpa.RpaVersion{
		Version:    param.Version,
		RpaVersion: param.RpaVersion,
	}

	_, err := s.checkVersion(ctx, ver)
	if err != nil {
		stark.Logger.Errorf(ctx, "RpaStart-err: %+v, param: %+v", err, param)
		return "", err
	}

	if param.TenantCode == "" || param.UserMobile == "" || param.Secret == "" {
		return "", errors.New("tenant_code or user_mobile or secret参数非法")
	}

	stark.Logger.Infof(ctx, "RpaStart-param: %+v", param)

	//// 1. 检查租户是否存在、租户是否购买了该产品，租户是否在租期内等
	////todo secKey缓存不存在则读库
	//cacheRedis, _ := cache.Redis()
	//cacheKey := fmt.Sprintf("gfyx-rpa-tenantcode:%s", param.TenantCode)
	//secKey, err := cacheRedis.Get(ctx, cacheKey)
	//if err != nil {
	//	return "", err
	//}
	//if secKey != param.Secret {
	//	return "", errors.New("非法密码")
	//}
	//
	//// 2. 检查账号是否存在
	//// todo：检查用户在租户下是否存在
	//
	//// 3. 生成jwt token
	//jwtToken, err := jwt.DefaultRpaJWT.GenerateRpaToken(param.TenantCode, param.UserMobile)

	request := &rpaPb.RpaStartRequest{
		UserMobile:  param.UserMobile,
		SecrectKey:  param.Secret,
		MachineCode: param.MachineCode,
		Version:     strconv.FormatInt(int64(param.Version), 10),
		RpaVersion:  param.RpaVersion,
	}

	resp, err := s.rpaRepository.RpaStart(ctx, request)
	if err != nil {
		stark.Logger.Errorf(ctx, "RpaStartr-err: %+v, param: %+v", err, param)
		return "", err
	}
	jwtToken := resp.Token

	return jwtToken, nil
}

// rpa命令处理入口
func (s *RpaCmdService) RpaCmdMain(ctx context.Context, param *rpa.RpaCmdData) (interface{}, error) {
	ver := rpa.RpaVersion{
		Version:    param.Version,
		RpaVersion: param.RpaVersion,
	}
	_, err := s.checkVersion(ctx, ver)
	if err != nil {
		return nil, err
	}

	// 初始化命令
	err = s.setCmdHandler(ctx, param)
	if err != nil {
		stark.Logger.Infof(ctx, "RpaCmdMain-setCmdHandler-err: %+v, param: %+v", err, param)
		return nil, err
	}

	switch param.Cmd {
	case RPA_CMD_POST:
		return s.rpaPost(ctx, param.Version, param.RpaVersion, param.Message)
	case RPA_CMD_GET:
		return s.rpaGet(ctx, param.Version, param.RpaVersion, param.Message)
	default:
		return nil, errors.New("不支持的命令，cmd只支持(post or get)")
	}
}

// 处理message
func (s *RpaCmdService) setCmdHandler(ctx context.Context, param *rpa.RpaCmdData) error {
	bussCmdMap, ok := s.rpaCmdMap[param.BussType]
	if !ok {
		return errors.New("该应用暂不支持")
	}

	cmdHandler, ok1 := bussCmdMap[param.Message.DataType]
	if !ok1 {
		return errors.New("该命令占不支持")
	}

	param.Message.CallHandler = cmdHandler

	return nil
}

// 上传数据
func (s *RpaCmdService) rpaPost(ctx context.Context, protoVersion int8, rpaVersion string, msg *rpa.RpaMessage) (interface{}, error) {
	switch protoVersion {
	case Rpa_Version_20231010.Version:
		return msg.CallHandler(ctx, protoVersion, rpaVersion, msg)
	default:
		return nil, errors.New("rpa版本不兼容")
	}
}

// 下载数据
func (s *RpaCmdService) rpaGet(ctx context.Context, protoVersion int8, rpaVersion string, msg *rpa.RpaMessage) (interface{}, error) {
	switch protoVersion {
	case Rpa_Version_20231010.Version:
		return msg.CallHandler(ctx, protoVersion, rpaVersion, msg)
	default:
		return nil, errors.New("协议版本不兼容")
	}
}
